package com.cloudkinto.service.serialmanage.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.cloudkinto.common.BeanConvert;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.extentity.OrderInputCountDto;
import com.cloudkinto.extentity.SerialNumberPageDto;
import com.cloudkinto.service.serialmanage.SerialNumberManageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;

import com.cloudkinto.service.serialmanage.vo.ProhibitOrRemoveReq;
import com.cloudkinto.service.serialmanage.vo.SerialNumberExcelImport;
import com.cloudkinto.service.serialmanage.vo.SerialNumberExportVo;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author zhujiale
 * @since 2022-09-22
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class SerialNumberManageServiceImpl extends ServiceImpl<SerialNumberManageDao, SerialNumberManageDo> implements SerialNumberManageService {
    @Autowired
    private SerialNumberManageDao dao;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private OrderInputDao orderInputDao;
    @Autowired
    private OrderInputPackageDao orderInputPackageDao;
    @Autowired
    private OrderInputProductDao orderInputProductDao;
    @Autowired
    private ProductSkuMapDao productSkuMapDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;

    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;

    @Override
    public SingleResult batchUpdate(ProhibitOrRemoveReq req) {
        req.getIds().forEach(et -> {
            SerialNumberManageDo manageDo = new SerialNumberManageDo();
            manageDo.setIsProhibitOutput(req.getIsProhibitOutput());
            manageDo.setId(et);
            dao.updateById(manageDo);
        });
        return SingleResult.success();
    }

    @Override
    public SingleResult pageInit() {
        List<Map> mapList = new ArrayList<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.orderByDesc("id");
        List<StorageDo> storageDoList = storageDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(storageDoList)) {
            storageDoList.forEach(storageDo -> {
                Map map = new HashMap();
                map.put("id", storageDo.getId());
                map.put("value", storageDo.getStorageName());
                mapList.add(map);
            });
        }
        return SingleResult.success(mapList);
    }

    @Override
    public SingleResult importInit(Long companyId) {
        List<Map> mapList = new ArrayList<>();
        List<OrderInputDo> orderInputList = orderInputDao.selectList(new QueryWrapper<OrderInputDo>().eq("company_id", companyId));
        if (!CollectionUtils.isEmpty(orderInputList)) {
            orderInputList.forEach(orderInputDo -> {
                Map map = new HashMap();
                map.put("id", orderInputDo.getId());
                map.put("value", orderInputDo.getOrderInputNumber());
                mapList.add(map);
            });
        }
        return SingleResult.success(mapList);
    }


    @Override
    public PageResult getListPage(Map<String, String> map) {
        IPage<SerialNumberPageDto> page = pageInit(map);
        List<SerialNumberPageDto> list = dao.getSerialNumberList(page, map);
        List<SerialNumberPageDto> resList = handlerListAfter(list);
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;

    }

    //查询分页列表之后对列表数据的处理
    private List<SerialNumberPageDto> handlerListAfter(List<SerialNumberPageDto> list) {
        list.forEach(et -> {
            if (et.getIsProhibitOutput() == 0) {
                et.setIsProhibitOutputCN("允许出库");
            } else {
                et.setIsProhibitOutputCN("禁止出库");
            }
            if (et.getOrderStatus().equals("waiting")) {
                et.setOrderStatusCN("待入库");
            } else if (et.getOrderStatus().equals("in")) {
                et.setOrderStatusCN("已入库");
            } else {
                et.setOrderStatusCN("已出库");
                et.setIsProhibitOutputCN("已出库");
            }
        });
        return list;
    }

    private IPage<SerialNumberPageDto> pageInit(Map<String, String> map) {
        IPage<SerialNumberPageDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }


    @Override
    public Object importSerialFile(MultipartFile file, Long orderInputId, Long userId, Long companyId) {
        if (file == null) {
            throw new BizException(SysConstant.Pls_Choose_File);
        }
        if (StringUtils.isEmpty(file.getName())) {
            throw new BizException(SysConstant.File_Name_Null);
        }
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) &&
                !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }
        List<SerialNumberExcelImport> serialExcelImports = new ArrayList<>();
        try {
            serialExcelImports = ExcelUtils.importExcel(file, 1, 0, SerialNumberExcelImport.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (serialExcelImports.size() == 0) {
            return SingleResult.success("");
        }
        //用来存放筛选合格的list
        List<SerialNumberExcelImport> list = new ArrayList<>();
        //用来存放错误集合的list
        List<String> errorList = new ArrayList<>();
        List<String> snList = new ArrayList<>();

        //这一层check检查的是excel中的数据是否为空以及序列号唯一性
        for (int i = 0; i < serialExcelImports.size(); i++) {
            int i1 = i + 2;
            SerialNumberExcelImport et = serialExcelImports.get(i);
            if (StringUtils.isBlank(et.getSerialNumber())) {
                continue;
//                errorList.add("第" + i1 + "行数据有误，序列号不能为空");
            }
            if (StringUtils.isBlank(et.getSku())) {
                errorList.add("第" + i1 + "行数据有误，SKU不能为空");
            }
//            if (StringUtils.isBlank(et.getBoxNumber())) {
//                errorList.add("第" + i1 + "行数据有误，箱单号不能为空");
//            }
//            if (StringUtils.isBlank(et.getTrayNumber())) {
//                errorList.add("第" + i1 + "行数据有误，托盘号不能为空");
//            }
            snList.add(et.getSerialNumber());
//            //序列号唯一性校验
//            int count = dao.selectCount(new QueryWrapper<SerialNumberManageDo>()
//                    .eq("serial_number", et.getSerialNumber())
//                    .eq("company_id", companyId));
//            if (count > 0) {
//                errorList.add("第" + i1 + "行序列号【" + et.getSerialNumber() + "】已存在");
//            }
//            //sku正确定检验
//            int count1 = productInfoDao.selectCount(new QueryWrapper<ProductInfoDo>()
//                    .eq("commodity_sku", et.getSku())
//                    .eq("company_id", companyId));
//            int count2 = productSkuMapDao.selectCount(new QueryWrapper<ProductSkuMapDo>()
//                    .eq("sub_sku", et.getSku())
//                    .eq("company_id", companyId));
//            if (count1 + count2 == 0) {
//                errorList.add("SKU【" + et.getSku() + "】不存在，请检查后重新尝试");
//            }
            //合格的放到新集合中
            list.add(et);
        }
        List<SerialNumberManageDo> serialNumberManageDoList = dao.selectList(new QueryWrapper<SerialNumberManageDo>()
                .in("serial_number", snList)
                .eq("company_id", companyId));
        if (serialNumberManageDoList.size() > 0) {
            for (SerialNumberManageDo serialNumberManageDo : serialNumberManageDoList) {
                errorList.add("序列号【" + serialNumberManageDo.getSerialNumber() + "】已存在");
            }
        }
        List<SerialNumberExcelImport> serialInputExcelImports = list.stream().filter(serialNumberExcelImport -> {
                    return StringUtils.isNotBlank(serialNumberExcelImport.getSerialNumber());
                })
                .collect(Collectors.toList());

        //这一层检测的是产品的数量
        if (errorList.size() == 0) {
            //判断导入的sku以及sku的数量是否与该订单吻合
            List<OrderInputCountDto> countList = dao.getOrderInputCountList(orderInputId);
            Map<String, List<SerialNumberExcelImport>> skuMap = serialInputExcelImports.stream().collect(Collectors.groupingBy(SerialNumberExcelImport::getSku));
            Map<String, List<SerialNumberExcelImport>> boxMap = serialInputExcelImports.stream().collect(Collectors.groupingBy(SerialNumberExcelImport::getBoxNumber));
            List<OrderInputPackageDo> packageDos = orderInputPackageDao.selectList(new QueryWrapper<OrderInputPackageDo>().eq("order_input_id", countList.get(0).getOrderId()));
            int packageCount = packageDos.stream().mapToInt(OrderInputPackageDo::getPackageCount).sum();
            if (boxMap.size() != packageCount) {
                errorList.add("该入库单下有【" + packageCount + "】个包裹(箱单)，而您导入的excel中有【" + boxMap.size() + "】种箱单号与之不符，请检查后再次尝试");
            }
//                for (OrderInputCountDto et : countList) {
//                    //check 入库单对应的sku信息
//                    List<SerialNumberExcelImport> list1 = skuMap.get(et.getCommoditySku());
//                    if (CollectionUtils.isEmpty(list1)) {
//                        errorList.add("您录取的SKU信息中缺少【" + et.getCommoditySku() + "】请检查后再次尝试");
//                    } else {
//                        if (et.getSkuCount() != list1.size()) {
//                            errorList.add("该入库单号下产品SKU为【" + et.getCommoditySku() + "】的数量为:【" + et.getSkuCount() + "】件，而您录入的为【" + list1.size() + "】件与之不符，请检查后再次尝试");
//                        }
//                    }
//                }
            //判断错误信息的list中是否有数据 有数据代表有错误 抛出500 前端展示
            for (SerialNumberExcelImport et : serialInputExcelImports) {
                SerialNumberManageDo insertDo = new SerialNumberManageDo();
                insertDo.setSerialNumber(et.getSerialNumber());
                insertDo.setOrderInputId(orderInputId);
                insertDo.setSku(et.getSku());
                insertDo.setBoxNumber(et.getBoxNumber());
                insertDo.setAboxNumber(et.getAoxNumber());
                insertDo.setTrayNumber(et.getTrayNumber());
                insertDo.setProductName(et.getProductName());
                insertDo.setName(et.getName());
                insertDo.setCustomerOrder(et.getCustomerOrderNumber());
                insertDo.setOrderStatus("waiting");
                insertDo.setPredictDate(DateUtils.stringFormatToDate(DateUtils.dateFormatToString(new Date(), null)));
                insertDo.setCreateBy(userId);
                insertDo.setCreateTime(new Date());
                insertDo.setCompanyId(companyId);
                insertDo.setProductId(getProductId(et.getSku(), companyId));
                dao.insert(insertDo);
            }
        }
        if (errorList.size() > 0) {
            return SingleResult.failure("300", "", errorList);
        } else {
            return SingleResult.success("");
        }
    }

    @Override
    public Object exportExcel(Map<String, String> map, String fileName) throws IOException {
        List<SerialNumberPageDto> list = dao.getSerialNumberList(map);
        if (list.size() > 9999) {
            throw new BizException(SysConstant.File_Export_ToMuch, 10000);
        }
        List<SerialNumberExportVo> exportVoList = new ArrayList<>();
        list.forEach(et -> {
            SerialNumberExportVo exportVo = BeanConvert.INSTANCE.serialNumberExportVo(et);
            if (et.getIsProhibitOutput() == 0) {
                exportVo.setIsProhibitOutputCN("允许出库");
            } else {
                exportVo.setIsProhibitOutputCN("禁止出库");
            }
            if (et.getOrderStatus().equals("waiting")) {
                exportVo.setOrderStatusCN("待入库");
            } else if (et.getOrderStatus().equals("in")) {
                exportVo.setOrderStatusCN("已入库");
            } else {
                exportVo.setOrderStatusCN("已出库");
                exportVo.setIsProhibitOutputCN("已出库");
            }
            exportVoList.add(exportVo);
        });
        ExportParams exportParams = new ExportParams();
        exportParams.setCreateHeadRows(true);
        exportParams.setHeaderColor(IndexedColors.YELLOW.getIndex());

        ExcelUtils.exportExcelToSave(exportVoList, SerialNumberExportVo.class, fileName, exportParams, filePathTemp);
        String objectNameTemporary = "";
        try {
            objectNameTemporary = AliOss.temporaryFile2(fileName, new File(filePathTemp + File.separator + fileName));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("导出文件失败" + e.getMessage());
        }
        return fileUrl + objectNameTemporary;
    }

    /**
     * 功能描述 根据sku和公司id获取产品id
     *
     * @author zhujiale
     * @date
     */
    private Long getProductId(String sellerSku, Long companyId) {
        QueryWrapper productWrapper = new QueryWrapper();
        productWrapper.eq("commodity_sku", sellerSku);
        productWrapper.eq("company_id", companyId);
        productWrapper.last("limit 1");
        ProductInfoDo productInfoDo = productInfoDao.selectOne(productWrapper);
        if (productInfoDo == null) {
            QueryWrapper skuWrapper = new QueryWrapper();
            skuWrapper.eq("sub_sku", sellerSku);
            skuWrapper.eq("company_id", companyId);
            skuWrapper.last("limit 1");
            ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
            if (productSkuMapDo == null) return null;
            return productSkuMapDo.getProductInfoId();
        } else {
            return productInfoDo.getId();
        }
    }

}
